>>>>>>>>>>>>>>>>  CVBasic user's manual  <<<<<<<<<<<<<<<<

                     by Oscar Toledo G.
              (c) Copyright 2024 Oscar Toledo G.
                    http://nanochess.org/

First developed: Feb/27/2024
Last revision: Apr/26/2025


>>>>>>>>>>>>>>  Legal notice

This software is provided 'as-is', without any express or implied warranty. 
In no event will the author be held liable for any damages or loss arising 
from the use of this software.

It is prohibited to modify, decompile, disassemble or reverse engineer this 
software.

All trademarks are property of their respective owners.


>>>>>>>>>>>>>>  Changes in this version

v0.8.0 Apr/26/2025  o Added support for Sega Master System using --sms
                    o Added support for VDP.STATUS (for reading VDP status)
                    o Added SELECT CASE / END SELECT
                    o Added support for CHR$ in PRINT (for portable printing of
                      arbitrary characters in the current cursor position)
                    o Added SCROLL statement for Sega Master System.
                    o Added BORDER flags for Sega Master System.
                    o Added PALETTE statement for Sega Master System.
                    o Adapted BITMAP, SCREEN, and SPRITE for Sega Master System.
                    o Optimizes code using directly DI/EI instructions in Z80
                      platforms if possible.

v0.7.1 Oct/15/2024  o Added support for NABU PC using --nabu (with -cpm option)
                    o Added support for USR/CALL with up to 5 arguments (only Z80)
                    o Added DEFINE VRAM READ to read VRAM.
                    o Added new example brinquitos.bas
                    o Added new example vramcopy.bas
                    o Optimizes division by 16 (Z80).

v0.7.0 Sep/03/2024  o Added support for Texas Instruments TI-99/4A --ti994a
                      (contributed by tursilion)
                    o Added suppprt for Hanimex/Soundic Pencil II using --pencil
                    o Added support for Tatung Einstein using --einstein
                    o Added support for Casio PV-2000 using --pv2000
                    o Added automatic protection code for mixer register (AY-3-8910)

v0.6.0 Aug/07/2024  o Added support for Creativision / Dick Smith's Wizzard (6502
                      processors!) using --creativision
                    o Added support for Sord M5 computers using --sord
                    o Added support for Memotech MTX computers using --memotech and -cpm
                    o Added VDP() command to set VDP registers.
                    o Added support for 16K of RAM in MSX using -ram16
                    o Optimizes 8-bit division by power of two.
                    o Optimizes pointer subtraction (VARPTR a(0) - VARPTR a(5))
                    o Added peephole optimizer for Z80 backend.

v0.5.1 Jun/25/2024  o Added SIGNED and UNSIGNED keywords to tag variables
                      (both 8-bit and 16-bit) and enable signed comparisons,
                      division, and modulo.
                    o The MSX target now supports 0-9, - and = for CONT1.KEY.
                    o Added new target Spectravideo SVI-318/328 (using
                      option --svi)
                    o Better assembler output for DATA.
                    o Optimized addition by 256.
                    o Optimized byte variable multiplied by 256.
                    o Optimized extra RET generated when using RETURN.
                    o Optimized use of Z flag.
                    o Optimized AND/OR/XOR of constant with 8-bit variable.
                    o Optimized code generation to avoid unnecessary PUSH/POP.
                    o More powerful optimization taking note of register usage.
                    o Reports open control block at end of procedure/program.
                    o Solved bug of undetected unfinished loop at global level.
                    o Solved bug of joystick not working in SC3000.
                    o Solved bug when subtracting two pointers (VARPTR)
                    o Solved bug where error would indicate wrong file (INCLUDE)
                    o Solved bug where Megacart didn't worked with --sgm, nor
                      the NTSC variable.

>>>>>>>>>>>>>>. Description

CVBasic is an integer BASIC compiler for Colecovision, MSX, Sega SG1000, Spectravideo SVI-318/328, Sord M5, Memotech MTX, Creativision, Soundic Pencil II, Tatung Einstein, Casio PV-2000, TI-99/4A, NABU PC, and Sega Master System.

It works as a cross-compiler over a PC and generates assembler code that can be processed by Gasm80.

Platforms requirements:
  o PC with Windows XP or better.
  o macOS X 10.6 or better (universal 32/64-bit binary)
  o Linux.

The current limitations are:
  o ASM cannot be used inside DEF FN.
  o Using PRINT for numbers always show numbers as unsigned from 0 to 65535.

Usage:
  
  cvbasic in.bas output.asm
  cvbasic --sg1000 in.bas output.asm
  cvbasic --msx in.bas output.asm
  cvbasic --msx -ram16 in.bas output.asm
  cvbasic --sgm in.bas output.asm
  cvbasic --svi in.bas output.asm
  cvbasic --sord in.bas output.asm
  cvbasic --memotech in.bas output.asm
  cvbasic --memotech -cpm in.bas output.asm
  cvbasic --creativision in.bas output.asm
  cvbasic --pencil in.bas output.asm
  cvbasic --einstein in.bas output.asm
  cvbasic --pv2000 in.bas output.asm
  cvbasic --ti994a in.bas output.a99
  cvbasic --nabu in.bas output.asm
  cvbasic --sms in.bas output.asm

The following modules are automatically included as the prologue and epilogue of your generated code and they set important variables and helper code:

  cvbasic_prologue.asm
  cvbasic_epilogue.asm

Afterwards, you should assemble your program using the included Gasm80 assembler.

  gasm80 output.asm -o output.rom

For Memotech you should use the .run extension or .com extension (if used -cpm option)

The Creativision port uses cvbasic_6502_prologue.asm and cvbasic_6502_epilogue.asm

The TI-99/4A port uses cvbasic_9900_prologue.asm and cvbasic_9900_epilogue.asm and it should be assembled using xdt tools. (xas99 with the -R option)

The NABU port requires the gasm output file to be named 000001.nabu and you should ZIP it to test it with MAME. If you use the -cpm option you can use any .com file name.

And finally, you can test the generated output.rom file using CoolCV, blueMSX, openMSX, or a Flash cartridge for real hardware.


>>>>>>>>>>>>>>  Supporting the developer

If you find CVBasic useful, please show your appreciation making a donation via Paypal ($9 USD suggested) to b-i+y-u+b-i (at) gmail.com

If you find a bug, please report to same email and I'll try to look into it. Because lack of time I cannot guarantee it will be corrected.


>>>>>>>>>>>>>>  CVBasic language specification
  
Execution starts at the first line of the BASIC program.

Syntax per line:
  [label:] statement[:statement] [' comment]

  MAIN:    PRINT "HELLO"  ' Prints hello
  
Multiple statements are allowed, but these must be separated by colons.

Variables are created simply by being used.

Labels are created simply by being used.

You can use a period before a label name to mark a local label. The local label's real name is based on the most recent global label (any label that doesn't start with a period) concatenated with the local label.

A variable name starts with a letter or # and is followed by letters, numbers, or the underscore character.

Variables and arrays (see DIM) can be 8-bit or 16-bit. Variables and arrays are 8-bit, if you want a 16-bit variable or array use # as the initial character of the variable's name.

    x
    y
    #score
    
Notice that if you use the # prefix you should use it everywhere in your program. Variables with the same name but without the # prefix are treated as different 8-bit variables.
    
All variables are initialized with the value 0 (zero) when they are created.

The following statements are available:

  REM comment      
  ' comment
  
     Everything between REM and the end of the line is treated by the compiler
     as a comment.

  SIGNED name[,name]
  
     Indicates that names are signed variables/arrays.

     This allows to use of signed comparisons, division, and modulo. Notice this
     adds extra code to extend sign on operations, and do signed comparisons.

     Typically you can develop your programs without using this keyword, but it's
     available if you really need it.

  UNSIGNED name[,name]
  
     Indicates that names are unsigned variables/arrays.

     This is the default behavior of variables/arrays in CVBasic.

  CONST [name]=[constant expression]
  
     Assign a name to a constant expression. The compiler will replace all
     instances of this name, in all expressions, with the number. These names
     have priority over variable names.

     This is like a compiler directive, it doesn't generate code and it can
     appear anywhere in the program but it will be treated as a constant from
     the point of appearance onwards.

     Constants that start with the # prefix are treated as 16-bit numbers, and
     if this isn't present then the constant will be treated as an 8-bit number.
  
  GOTO label        
  
     Go to label.

     It's erroneous to jump from inside a PROCEDURE to outside of the same
     PROCEDURE. 

  GOSUB label       
  
     Go to a subroutine located at label (must be a PROCEDURE).
  
  label: PROCEDURE
  [code for subroutine]
  END
  
     Create a PROCEDURE callable by GOSUB.

     It's important that PROCEDURE is on the same line as the label.

     END implies an automatic RETURN.

  RETURN            
  
     Return from subroutine (PROCEDURE). Also can be used for an early return from a
     PROCEDURE.

  FOR A=start TO end [STEP increment]
  NEXT     ' Also supported NEXT A
  
  FOR A=1 TO 5 ' Loop
    [Variable A will contain 1,2,3,4,5]
  NEXT A
  
  FOR A=1 TO 5 STEP 2
    [Variable A will contain 1, 3, 5]
  NEXT A
  
  FOR A=5 TO 1 STEP -2
    [Variable A will contain 5, 3, 1]
  NEXT A
  
     Looping statement.
     
     The start, end, and step expressions can be complex expressions, instead of
     only constants or variables.

     Notice that you can only use regular variables for the loop variable, not
     array variables. There is a small quirk if you're using an 8-bit variable
     and the TO expression is pretty complex and reaches 0 or 255, the loop can
     be infinite.
     
  WHILE expr:[statement]:WEND
  WHILE expr
  [statement]
  WEND
  
     Looping statement that keeps looping as long as the expression evaluates
     to non-zero.
     
  DO WHILE expr:[statement]:LOOP
  DO WHILE expr
    [statement]
  LOOP

  DO UNTIL expr:[statement]:LOOP
  DO UNTIL expr
    [statement]
  LOOP
  
  DO:[statement]:LOOP WHILE expr
  DO
    [statement]
  LOOP WHILE expr
  
  DO:[statement]:LOOP UNTIL expr
  DO
    [statement]
  LOOP UNTIL expr
  
     Looping statements that keep looping WHILE expression evaluates to
     non-zero, or UNTIL expression evaluates to non-zero.

  EXIT FOR
    
     Exits current FOR loop. It jumps directly to the line that follows NEXT.

  EXIT WHILE
  
     Exits current WHILE loop. It jumps directly to the line that follows WEND.
     
  EXIT DO
     
     Exits current DO loop. It jumps directly to the line that follows LOOP.

  IF expr GOTO [label]
  IF expr THEN [statement]
  IF expr THEN [statement] ELSE [statement]

  IF expr THEN
    [statement]
  END IF
  
  IF expr THEN
    [statement]
  ELSE
    [statement]
  END IF
  
  IF expr THEN
    [statement]
  ELSEIF expr THEN
    [statement]
  END IF

  IF expr THEN
    [statement]
  ELSEIF expr THEN
    [statement]
  ELSE
    [statement]
  END IF

     Decision statement. The first statement is taken if the expression result
     is non-zero.


  ON expr GOTO [label],[label],[label]
  ON expr GOTO [label],,[label]
  ON expr GOTO ,,[label]
  ON expr GOSUB [label],[label],[label]
  ON expr GOSUB [label],,[label]
  ON expr GOSUB ,,[label]
  ON expr FAST GOTO
  ON expr FAST GOSUB

     Decision statement

     The expression is evaluated and if the result is zero, the first label
     is taken, if the result is one, the second label is taken, and
     successively up to any number of labels.

     If GOSUB is used then you must make sure that each label is linked to
     a PROCEDURE.

     If an option has no label or if the expression exceeds the number of
     labels, the execution flow continues with the following statement
     after ON.

     This statement can be made faster in execution using the FAST modifier,
     it will avoid checking boundaries, but if your list of labels doesn't cover
     the full expression range then your PROGRAM WILL CRASH.

  SELECT CASE expr
     CASE 1
       [statement]
     CASE 2 TO 4
       [statement]
     CASE ELSE
       [statement]
  END SELECT

     It evaluates the expression, and selects the statements to execute from the
     CASE statements. CASE ELSE should be the last statement if it is required to
     handle non-specified values. You can exit using EXIT SELECT.

  ON FRAME GOSUB label
  
     On each video frame interrupt, the CVBasic core will call the indicated
     PROCEDURE.

     This doesn't generate any code and should only appear once in your program.
     Also, it’s important to keep in mind this procedure could be called even
     before your initialization routines are executed.

     The only valid assumption is that every single variable is zero after
     booting. It's your responsibility that the code doesn't take too long to
     execute, otherwise video frame interrupts will accumulate, and your memory
     stack will overflow.

     If you are using bank-switching the procedure should be located in bank 0
     (this is after BANK ROM and before any BANK number statement).

  POKE address,data
  
     Poke memory with data.

  VPOKE address,data

     Poke VRAM with data.

  WAIT
  
     Waits for the next frame interruption (1/60 of a second for NTSC or 1/50
     of a second for PAL)

  OPTION WARNINGS ON
  OPTION WARNINGS OFF

     Enable/disable the compilation warnings. Note that if you disable warnings
     at the end of your program, you won't have the list of non-used variables.

  OPTION EXPLICIT
  OPTION EXPLICIT ON
  OPTION EXPLICIT OFF

     Makes it mandatory to declare each variable with DIM before said variable
     can be used.

  DIM variable
  DIM variable[,variable]
  
     Declares a variable.
     
     Useful in combination with OPTION EXPLICIT.
     
  DIM var(size)
  
     Creates an array of data called 'var' of 'size' elements.
     Counting starts on zero, so DIM A(10) creates an array of 0 to 9.
     
     Also you can create arrays of 16-bits numbers, using the # sign
     as the first letter of the array name DIM #BIG(10)

     The array can be accessed as follows:
     
         A(1)=A(1)+5
         A(X)=A(Y)-2
         
     The DIM statement is like a directive, it doesn't generate code
     and it can appear anywhere in the program. The definition will start
     from the line of the DIM statement.

  RESTORE label

     Restores the READ pointer to start at the provided label.

  READ var
  READ BYTE var

     Reads a 16-bit value and puts it into the variable var.

     It can also read an 8-bit value and put it into the variable var.

     Make sure you pair correctly READ/DATA and READ BYTE/DATA BYTE,
     as otherwise the internal pointer will get desynchronized.

  DATA constant_expr[,constant_expr]
  DATA BYTE constant_expr[,constant_expr]
  DATA BYTE string
  DATA VARPTR a
  DATA VARPTR b(constant_expr)

     Defines 16-bit data to be stored in program memory, or also 8-bit data.

     DATA statements should be referred with a label starting with the # sign,
     and DATA BYTE statements should be referred to with a label not starting
     with the # sign.

     All data contained in DATA can also be accessed using the familiar
     array-indexing syntax, like this:
    
       FOR A=0 TO 4
       PRINT AT #TABLE(A),"Z"
       NEXT A
      
       #TABLE:
       DATA 21,42,63,84,105

  DEFINE CHAR char_num,total,label
  DEFINE CHAR char_num,total,VARPTR array(expr)
  DEFINE CHAR PLETTER char_num,total,label

     Loads graphics into VRAM.

     "char_num" valid values are between 0 and 255.

     "total" valid values are between 1 and 256.

     It replaces the definitions for "char_num", "total" means the total number
     of characters to load, and "label" should point to a label containing
     BITMAP statements or DATA BYTE statements.

     Each character is an 8x8 pixel bitmap (represented as 8 BITMAP statements or
     8 constants in a DATA BYTE statement). For Sega Master System, this is 32
     constants in a DATA BYTE statement because the character definition includes
     color.

     Internally, CVBasic will replicate the data along the 3 display areas so
     the defined characters will appear on the whole screen when required.

     The VARPTR expression allows character definition from an offset inside an
     array so you can do animation easily.

     Use the optional argument PLETTER to indicate that the data is compressed
     with the Pletter compressor (TMSColor does the compression if you give the
     option -z)

  DEFINE COLOR char_num,total,label
  DEFINE COLOR char_num,total,VARPTR array(expr)
  DEFINE COLOR PLETTER char_num,total,label

     Loads color into VRAM. This sentence isn't used on Sega Master System.

     "char_num" valid values are between 0 and 255.

     "total" valid values are between 1 and 256.

     It replaces the colors for "char_num", "total" means the total number
     of characters to load, and "label" should point to a label containing
     DATA BYTE statements.

     The color format is the standard one of the TMS9118 Video Display processor.
     Each character is composed of 8 rows, and each row can have a foreground
     color (upper nibble), and a background color (lower nibble).

     Internally, CVBasic will replicate the data along the 3 display areas so
     the defined characters will appear on the whole screen when required.

     The VARPTR expression allows color definition from an offset inside an
     array so you can do animation easily.

     Use the optional argument PLETTER to indicate that the data is compressed
     with the Pletter compressor (TMSColor does the compression if you give the
     option -z)

  DEFINE SPRITE sprite_num,total,label
  DEFINE SPRITE sprite_num,total,VARPTR array(expr)
  DEFINE SPRITE PLETTER sprite_num,total,label

     Loads sprites into VRAM

     "sprite_num" valid values are between 0 and 63 (127 for Sega Master System)

     "total" valid values are between 1 and 64 (128 for Sega Master System)

     It replaces the definitions for "sprite_num", "total" means the total number
     of sprites to load, and "label" should point to a label containing
     BITMAP or DATA BYTE statements with the sprite or sprites representation.

     Each sprite is 16x16 pixels (8x16 pixels for Sega Master System)

     The VARPTR expression allows sprite definition from an offset inside an
     array so you can do animation easily.

     Use the optional argument PLETTER to indicate that the data is compressed
     with the Pletter compressor (TMSColor does the compression if you give the
     option -z)

  DEFINE VRAM address,length,label
  DEFINE VRAM address,length,VARPTR array(expr)
  DEFINE VRAM PLETTER address,length,label

     Copies data from "label" into VRAM address "address".
     The total of bytes is defined by "length".

     The VARPTR expression allows choosing the origin from an offset inside an
     array so you can do animation easily.

     Use the optional argument PLETTER to indicate that the data is compressed
     with the Pletter compressor (TMSColor does the compression if you give the
     option -z)

  DEFINE VRAM READ address,length,label
  DEFINE VRAM READ address,length,VARPTR array(expr)

     Copies data from VRAM address "address" into "label".
     The total of bytes is defined by "length".

     The VARPTR expression allows choosing the origin from an offset inside an
     array.

  SOUND 0,[value 10 bits],[vol 0-15]
  SOUND 1,[value 10 bits],[vol 0-15]
  SOUND 2,[value 10 bits],[vol 0-15]
  SOUND 3,[control 4 bits],[vol 0-15]

     Allows to generate tones on the SN76489 sound processor. Volume values
     are 0 for no sound and 15 for the highest sound.


     The desired frequency value can be calculated this way:
   
         value = 3579545 / 32 / frequency

     Only a constant can be used as the first parameter of SOUND.

     The SN76489 allows four independent tones to be played at the same time.

     The first three channels are pure tones, and the fourth channel can be
     white noise (4<= control <= 7) or a tone with a special shape
     (0<= control <= 3)

     The frequency for the fourth channel is fixed (control is 0,1,2,4,5,6)
     or related to the frequency of the third channel (control is 3,7)

     If you use the music player, the SOUND capabilities are affected. Refer
     to the PLAY statement later for further information.

  SOUND 5,[VALUE 12 bits],[VOL 0-15]       Channel A
  SOUND 6,[VALUE 12 bits],[VOL 0-15]       Channel B
  SOUND 7,[VALUE 12 bits],[VOL 0-15]       Channel C
  SOUND 8,[VALUE 16 bits],[TYPE 0-15]      Volume envelope (frequency/shape)
  SOUND 9,[NOISE 5 bits],[MIX]      Noise and mix register ($b8 value by default)

     Allows to generate tones on the AY-3-8910 sound processor (MSX). Volume
     values are 0 for no sound and 15 for the highest sound.


     For channels A, B and C, if you use volume 16 the PSG will use the
     volume envelope (see SOUND 8)
    
     If you use the music player, the SOUND capabilities are affected. Refer
     to the PLAY statement later for further information.

     NOTE: USE ONLY VALUES $80-$BF FOR MIX BECAUSE ANY VALUE OUTSIDE THIS
           CAN BURN YOUR MSX HARDWARE.

  SPRITE index,y,x,f,c
  SPRITE index,y,x,f

     The first parameter indicates the number of the sprite (0-31).

     Y contains the Y-coordinate for the top row of the sprite.
     The final result is one pixel below the expected pixel row, so you
     must subtract one.

     X contains the X-coordinate for the sprite (0-255)

     F contains the sprite frame. You must multiply the desired sprite
     definition (0-63) by 4 to show the right sprite. For Sega Master
     System the sprite frame is based on 8x8 blocks, so you need to use
     multiplies of 2 for each 8x16 sprite (0-254)

     C contains the color for the sprite (0-15). Alternatively, you can
     add the flag $80 (128 decimal) to displace the sprite by 32 pixels
     to the left. Allowing it to blend inside the screen from the left.

     The fourth argument (color) isn't used on Sega Master System, and
     it will generate an error from CVBasic if present.

     Sprites are updated on the vertical retrace.

     The Y-coordinate visible range for sprites is 240 to 255, and 0
     to 190. 240-254 allows the sprite to enter smoothly from the top,
     255 is the top pixel row of the screen, and 0-190 is the whole
     vertical range of the screen (190 is the bottom pixel row of
     the screen). Values 191-239 make the sprite invisible.

     Additionally, the value 208 for the Y-coordinate disables sprite
     processing starting on that very sprite. For example,
     SPRITE 0,$d0,0,0,0 forces sprites 1-31 to disappear even if active.


  SPRITE FLICKER ON
  SPRITE FLICKER OFF

     Turns sprite flicker on and off. By default, CVBasic will start with
     SPRITE FLICKER ON, this enables a code snippet that cycles sprites on
     the screen to circumvent the VDP limitation of 4 sprites in a row.

     If you turn it off, you can use the VDP limitation to make certain
     tricks, for example, putting black sprites for masking sprites in
     borders, overlapping sprites in different depths, or using the
     SPRITE 0,$d0,0,0,0 trick.

  OUT port,data

     It outputs "data" in the hardware port "port". Not available in 6502 targets.

  CLS

     Clears the screen. The screen buffer is filled with the value 32 (equivalent to ASCII space character).

     Also, it resets the internal cursor position to the top-left corner of the screen.

  PRINT [AT [expr]][,]["string"]

     Prints the given string at the current cursor coordinate (or
     selected via the AT value 0 to 767).

     The string is processed in ASCII, and CVBasic automatically
     defines the ASCII charset to be available at the start. You can
     redefine all the characters if required.

     If you want to use a character beyond the printable ones, you
     can use the inverted slash as an escape character (by example
     "\128\129")

     If you want to use double quotes inside a string you can
     escape it this way: \"

     Examples of positioning:

         PRINT AT 0,"A"    ' Upper-left corner
         PRINT AT 31,"A"   ' Upper-right corner
         PRINT AT 736,"A"  ' Bottom-left corner
         PRINT AT 767,"A"  ' Bottom-right corner

  PRINT expr
  PRINT <const>expr     ' Right-aligned with zeroes to 'const' size.
  PRINT <.const>expr    ' Right-aligned with spaces to 'const' size.

     Displays expr as an ASCII number using characters between 48 and 57.

     Example:

        PRINT AT 8,"Score:",<5>#score,"00"

  PRINT CHR$(expr)

     Displays expr as a character on the video screen.

     Example:
 
        PRINT CHR$(65)

  BORDER color
  BORDER color,flags

     Select the border color. It can be a number from 0 to 15.

     The flags argument is available on Sega Master System.
        bit 0 = Set column 0 to border color.
        bit 1 = Horizontal scrolling disabled on rows 0-1.
        bit 2 = Vertical scrolling disabled on columns 24-31.

  SCROLL x, y

     Sets the pixel scrolling for Sega Master System background.

  PALETTE register, color
  PALETTE LOAD array_data_byte
  PALETTE LOAD VARPTR array_data_byte(0)

     Sets a single palette register (0-31) to the color (0-63). Color bits are
     specified in a single byte as 00BBGGRR (two bits each for red, green, and
     blue).

     The registers 0-15 are for background tiles, and the registers 16-31 are
     for sprites. The tiles can request to use the sprite colors.

     Alternatively, you can load a full 32 entries palette using PALETTE LOAD.
     The array should be specified with DATA BYTE.

  MODE 0

     Select the video mode 0. In this mode, the 32x24 screen grid can have one
     of the 256 characters in each grid square.

     Each 8x8 pixel character can have a bitmap. Each line of a character
     can have two colors. For example, $f1 is a white foreground and black
     background.

           0 - Transparent.     8 - Red.
           1 - Black            9 - Light red.
           2 - Green            a - Yellow. 
           3 - Light green.     b - Pale yellow.
           4 - Dark blue.       c - Dark green.
           5 - Blue.            d - Purple.
           6 - Dark red.        e - Gray.  
           7 - Cyan.            f - White.

  MODE 1

     Select the video mode 1. This is a high-resolution video mode where
     you can address each pixel individually.

     Useful for graphics artwork filling the screen. Notice there is no
     preloaded font for the screen, you should load individually the
     graphics needed at any time.

  MODE 2

     This video is pretty similar to MODE 0, except it is faster for defining
     bitmaps for the characters. Also, there is a limitation where the color for
     characters is limited to a foreground/background color for each 8 characters.

     VRAM addresses $2000-$201f contain the color for the characters group.

  MODE 4

     It is only available on Sega Master System, and it is the only mode supported
     in this console. VRAM $0000-$1fff are setup as background bitmaps, $2000-$37ff
     for sprites bitmaps, $3800-$3dff for the background patterns, and $3f00-$3fff
     for the sprites attributes. The unused portion $3e00-$3eff and $3f40-$3f7f 
     can be used for extra sprites (sprite numbers 120-123 and 125)

  SCREEN DISABLE

    Disables the video output. The current color of the border will fill the
    screen (can be set up using the BORDER statement). The video can be enabled
    again with SCREEN ENABLE or using a MODE statement.

  SCREEN ENABLE

    Enables the video output (preserves the previous video mode set by MODE).

  SCREEN label[,origin_offset,target_offset,cols,rows]
  SCREEN label[,origin_offset,target_offset,cols,rows,origin_width]

    This statement is the fastest way to copy screen data to video. Using only
    "SCREEN label” copies a full screen of 32x24 characters to video.

    'label' points to a label inside your program containing the data for the
    screen, similar to this:
    
      my_screen:
         DATA BYTE "Top-left corner..." ' It continues...
        
    origin_offset is the offset inside the origin data.
    target_offset is the offset (0-767) inside the target video screen.
    cols is the horizontal size (number of columns) of your copy.
    rows is the vertical size (number of rows) of your copy.
    origin_width is the origin data width, useful to copy a sub-portion of a
                 big graphic screen, like a map, or when scrolling horizontally.
                 If this parameter is not used, the default value is the same
                 as "cols".
    
    This can serve to move large elements in video or to display beautiful 
    graphics screens.
    
    Label can be also a 8-bit array for dynamically drawn elements.
    
        DIM tile(4)
        
        SCREEN tile,0,0,2,2

    For the Sega Master System the source offset, target offset, and width are
    automatically multiplied by 2, because each character in the screen uses
    two bytes in VRAM. The first byte referring to the tile number (0-255), and
    the second byte specifies how it is used:

        bit 0 - Indicates to use tiles in the range 256-511
        bit 1 - Horizontal flip if set.
        bit 2 - Vertical flip if set.
        bit 3 - Uses sprite palette if set.
        bit 4 - The tile will be drawn on top of sprites.

  BITMAP "00000000"
  BITMAP "00001111"
  
  BITMAP "________"
  BITMAP "____XXXX"
  
    Allows you to draw using binary.

    For characters, you should use 8 BITMAP statements containing 8 pixels each
    to form a graphic definition.

    For sprites, you should use 16 BITMAP statements containing 16 pixels each.
    
    This is most useful when attaching a label and using it with DEFINE CHAR and
    DEFINE SPRITE.
    
    Characters taken as zero include: "0" "_" " " "."

    Every other character will be interpreted as one.

    For the Sega Master System, the sprites are composed by 8x16 pixels. If you
    use a 16x16 bitmap, it is automatically divided into 2 sprites of 8x16 pixels.
    The colors for each pixel are specified by using hexadecimal digits 1 to 9,
    and A to F.


  PLAY SIMPLE
  PLAY SIMPLE NO DRUMS
  PLAY FULL
  PLAY FULL NO DRUMS
  
    Activates music player and selects the type of music played, SIMPLE only
    uses two channels, allowing the programmer to use SOUND 2 for sound effects
    (or SOUND 7 in MSX).
    
    FULL will use all three channels, so SOUND cannot be used in this context.
    
    The music player plays drums using the noise channel and the mix register.
    You can deactivate this feature using the NO DRUMS syntax, for example, if
    you want to generate explosion sounds with the noise channel, allowing you
    to use SOUND 3 (or SOUND 9 in MSX).

    Notice that the music player will update the sound channels on every video
    frame.


  PLAY NONE
  
    Deactivate the music player. Following this the programmer should turn off all
    the sound channels, using this code for Colecovision or SG1000:
    
      SOUND 0,,0
      SOUND 1,,0
      SOUND 2,,0
      SOUND 3,,0

    For MSX you need to do this:

      SOUND 5,,0
      SOUND 6,,0
      SOUND 7,,0
      SOUND 9,,$38

  PLAY label
  
    Plays the music pointed by 'label'.
    
    CVBasic will include automatically extra code for the music player.
    
    Music must be in this format: (each MUSIC statement can contain up to 4
    arguments)
    
        label:  DATA BYTE 8         ' Ticks per note (there are 50 ticks per second)
                MUSIC F4,A4#,C5
                MUSIC S,S,S
                MUSIC -,-,-

                MUSIC REPEAT
                MUSIC STOP

                MUSIC C4,F4,- ' Note how C4 extends along 4 tempos and F4 only 2
                MUSIC S,S,-
                MUSIC S,-,-
                MUSIC S,-,-
                
    Identifiers for notes: Note C, D, E, F, G, A, B followed by an octave (2-6), C7
                           is also available.

                           Optionally add the # sign for sharp.

                           Optionally add W, X, Y or Z to specify the instrument.
                           (W for piano, X for clarinet, Y for flute and Z for bass)
                           
                           Setting the instrument carries over in each channel for
                           MUSIC statements played afterward if the instrument
                           is not specified thereafter.
                           
                           Notice that the instrument waveforms can be altered
                           by modifying the cvbasic_epilogue.asm file for your
                           program.

                           Notice the bass instrument reduces two octaves your
                           current note, anything under octave 4 will be
                           silent with Colecovision SN76489 (not applies to
                           MSX AY-3-8910)

                           Also, the programmer can put S to sustain previous note,
                           or can put - for silence.
        
                           The fourth argument for MUSIC allows simple drums:

                             Valid values are:
                                -  none
                                M1 strong
                                M2 tap
                                M3 roll

    CVBasic will detect automatically PAL/NTSC Colecovision and will adjust 
    music timing and frequencies accordingly.

    If you are using bank-switching you can play music from a different bank
    (see BANK SELECT).

  PLAY OFF
  
    Stops music, if music is currently playing.
    

  DEF FN func = RANDOM % 10
  DEF FN screen_off(row, col) = (row * 32 + col)
  DEF FN resetsprite(number) = SPRITE number,$d1,0,0,0

    Allows to define functions with any number of arguments.
    
    Notice that these are processed like macros: The arguments are replaced
    as-is and the text of the function is inserted as-is after argument
    replacement. (because of that are included the extra parenthesis in the
    screen_off expression)

    For example, the two functions screen_off and resetsprite could be called as:
    
          A = func
          PRINT AT screen_off(4,8),"HELLO!"
          resetsprite(0)

    Please note that although it's possible to reuse internal function names,
    when called the internal functions have priority over DEF FN (DEF FN is
    ignored)

  INCLUDE "filename.bas"
  
    Includes the contents of another source file inside the current CVBasic
    program. 

    INCLUDE allows you to include external code anywhere in your program.
    You could even have half of a procedure in the main file and the rest of it
    in the included file.

    This is very useful for separating graphics and screen files.

  VDP(reg) = expr

    Sets the VDP register to the expression value.

  CALL NAME       
   
    Calls assembly function NAME without arguments. Note CVBasic will put the
    NAME all in uppercase.

  CALL NAME(expr)  
  CALL NAME(expr,expr)  

    Calls assembly function NAME with one argument in HL (or Y,A for 6502)
    (Up to five arguments in Z80. HL, DE, BC, IX and IY).

  ASM code
  
    Allows you to insert assembly code code directly into your source code.
    The line content is copied directly to the output. It's also very useful
    to include assembly code modules, like this:
    
        ASM INCLUDE "yourfile.asm"

  BANK ROM 128
  BANK ROM 256
  BANK ROM 512
  BANK ROM 1024

    This statement allows you to use 128K-1024K cartridges for your program
    (Opcode's Megacart for the Colecovision, ASCII 16K mapper for MSX, and
    SMS Sega Mapper for SG1000).
    
    It should be the very first statement in your program. 128 allows for
    8 banks, 256 allows for 16 banks, 512 allows for 32 banks, and 1024 allows
    for 64 banks. Each bank measures 16 kilobytes.

    After this statement, your CVBasic program will continue at bank 0 (the
    global bank).

    In bank 0 you should have global procedures and data that are shared by
    all your banks.

  BANK 1-63

    Select the bank for the following code/data of your program. Each bank can
    contain up to 16319 bytes, and it is located in a separate area from the
    bank 0.

    Although you can use banks in any order, you cannot repeat bank numbers or
    use BANK 0 (this is done for you when using BANK ROM).

  BANK SELECT 1-63

    Selects a bank to access for the following statements. You can call
    procedures in the bank, or access data from the bank.

    BANK SELECT only can be used inside bank 0, otherwise, CVBasic will
    crash (like trying to change a carpet while standing over it).
        

>>>>>>>>>>>>>>  Expression syntax

The expression syntax is like a calculator.

The usual precedence rules apply to expression operators. Addition and
subtraction have lower precedence than multiplication and division. This means
1 + 2 * 3 = 7 not 9.

The expression parser will take advantage of 8-bit variables and numbers to optimize the code. If you want a variable to "become" 16-bit you need for example to add a 16-bit number to it.
  
  A=5               Decimal number (16 bits)
  A=5.              Decimal number (8 bits)
  A=$1000           Hexadecimal number
  A=&10101          Binary number
                    
  A="C"             ASCII code for letter (8 bits)
  A=B               Simple assignment
  A=A+B             Simple addition
  A=A-B             Simple subtraction
  A=A*B             Simple multiplication
                    Multiplication by 2/4/8/16/32/64/128/256 is
                    internally optimized.
  A=A/B             Simple unsigned division.
  A=A%B             Simple unsigned remainder.
  A=(A+B)-C
  A=A AND B
  A=A OR B          
  A=A XOR B
  A=NOT A
  A=-A
  A=A=B             If A and B are the same the result is $ffff (-1) else zero
  A=A<>B
  A=A<B
  A=A>B
  A=A<=B
  A=A>=B
  A=PEEK(expr)      Reads a memory location
                    PEEK always reads 8-bit data that can be processed in
                    an expression.
  A=VPEEK(expr)     Reads a VRAM memory location
                    VPEEK always reads 8-bit data that can be processed in
                    an expression.
  A=ABS(expr)       Gets the absolute value of the expression (non-negative)
  A=SGN(expr)       Gets sign of expression (-1, 0 or 1)
  A=array(expr)     Accesses an array. The array can be defined with DIM or
                    label for DATA
  array(expr)=A     Writes data to an array. The array can be defined with DIM.
                    DATA is not writable

  A=USR NAME        Calls assembly function NAME (all in uppercase) without
                    arguments, and expects a result in HL.
  A=USR NAME(expr)  Calls assembly function NAME with one argument in HL, and
                    expects a result in HL (or Y,A for 6502).
  A=USR NAME(expr1,expr2) Calls assembly function NAME with one argument in HL
                    and the second one in DE (third would be BC, fourth would
                    be IX, and fifth would be IY). Only for Z80.

  #A=VARPTR B       Gets a pointer to a variable. Useful when linking assembler
                    routines.

  #A=VARPTR C(0)    Gets a pointer to an array. Can be defined with DIM or label
                    for DATA.

  CONT              Contains the state of both controllers.
  CONT.UP           Non-zero if any controller pointing up
  CONT.DOWN         Non-zero if any controller pointing down
  CONT.LEFT         Non-zero if any controller pointing left
  CONT.RIGHT        Non-zero if any controller pointing right
  CONT.BUTTON       Non-zero if any controller left button is pressed.
  CONT.BUTTON2      Non-zero if any controller right button is pressed.
  CONT.KEY          Current pressed key in any controller (0-9 for numbers,
                    10-*, 11-#, 15-Not pressed)

  CONT1             Contains the state of the first controller.
  CONT1.UP          Non-zero if controller pointing up
  CONT1.DOWN        Non-zero if controller pointing down
  CONT1.LEFT        Non-zero if controller pointing left
  CONT1.RIGHT       Non-zero if controller pointing right
  CONT1.BUTTON      Non-zero if the controller left button is pressed.
  CONT1.BUTTON2     Non-zero if the controller right button is pressed.
  CONT1.KEY         Current pressed key (0-9 for numbers, 10-*, 11-#, 15-Not pressed)

  CONT2             Contains the state of the second controller.
  CONT2.UP          Non-zero if controller pointing up
  CONT2.DOWN        Non-zero if controller pointing down
  CONT2.LEFT        Non-zero if controller pointing left
  CONT2.RIGHT       Non-zero if controller pointing right
  CONT2.BUTTON      Non-zero if the controller left button is pressed.
  CONT2.BUTTON2     Non-zero if the controller right button is pressed.
  CONT2.KEY         Current pressed key (0-9 for numbers, 10-*, 11-#, 15-Not pressed)

  RANDOM
    Produces a pseudo-random value between 0 and 65535.
    The value produced is different each time.
    
  RANDOM(range)
    Produces a pseudo-random value between 0 and range-1.
    The value produced is different each time.

  LEN(string)
    Returns the length of a string. Very useful in combination
    with DEF FN, for example, for creating strings centered on
    the screen.   

  POS(expr)
    Returns the current screen position (useful for PRINT AT)
    The expression is analyzed but no code is generated.

  INP(expr)
    Reads 8-bit data from the I/O port expr. Not available in 6502 targets.

  FRAME
    Returns the current frame number (0-65535, it cycles back to
    0 after reaching 65535)

  NTSC
    Returns 1 if the Colecovision is an NTSC console, otherwise
    returns zero.

  VDP.STATUS
    Returns the current status of the Video Display Processor. It is
    updated on each video frame.

  MUSIC.PLAYING
    Returns zero if music is not currently playing, returns a non-zero
    value otherwise.
    

>>>>>>>>>>>>>>  Useful VRAM addresses

Currently CVBasic handles in its own the bitmap, color and sprites tables.

However, you probably will need direct access to the screen.

The screen is a 32x24 grid located at the VRAM address $1800-$1aff. It can be accessed using VPOKE (writing) and VPEEK (reading).

See the included example viboritas.bas for examples.


>>>>>>>>>>>>>>  Assembly language interfacing

The USR expression and the CALL statement allow you to call assembly language
modules from inside CVBasic programs. Note the label name for assembly
language modules is translated to uppercase.

CVBasic expect the following conventions to be preserved:

    Before calling:
    
    HL = Value of first argument (or trash)

    After calling:

    HL = Value from assembly language module (only USR expression)

If your module changes the address of the Stack Pointer (SP) then there is
a high probability that the CVBasic program will crash.

How your function should look:

    ASM MYFUNCTION:    
    ASM                ; ... your code...
    ASM                RET
    
    
>>>>>>>>>>>>>>  Some further notes

A program’s execution is sequential unless interrupted by GOTO or GOSUB. In any
of your programs, you should put GOTO at the end of the main block, otherwise
execution could run in undesirable ways. For example:

Example 1:

    A = 5
  stop:	GOTO stop	' Prevents CVBasic running out of ROM


Example 2:

    A = 5
  stop:   GOTO stop	' Prevents execution running inside procedure

  test:	PROCEDURE
		END
        
If you insert PROCEDURE, DATA, or MUSIC data in the middle of the
execution sequence, the Z80 processor will do strange things. So you
must put your data at the end of the program or where the execution doesn't
reach it.

Example 3:

    A = 6
    DATA 5,6,7      ' Bad, this gets executed! move it after the GOTO
  stop:    GOTO stop
        
By default, CVBasic programs can be so big as 32 kilobytes. The starting
address for Colecovision is $8000, MSX is $4000, and SG1000 is $0000.

You can measure your program by checking the generated LST file created by
the assembler.
         
     
>>>>>>>>>>>>>>  Permissions in Mac OS X and Linux

The provided executables for both Mac OS X and Linux probably will not have
the right permissions when uncompressed.

So is suggested to run these commands in your CVBasic directory:

  chmod 755 cvbasic
  chmod 755 cvbasic_linux

If your CVBasic directory is not in the current path you can run it using this
while at CVBasic directory:

  ./cvbasic game.bas game.asm


>>>>>>>>>>>>>>  Useful links

CoolCV emulator

  https://forums.atariage.com/topic/240800-coolcv-emulator-for-mac-os-x-linux-windows-and-raspberry/

  
>>>>>>>>>>>>>>  Acknowledgments

Thanks to following members of Atariage for contributing valuable suggestions:

  ARTRAG
  gemintronic
  Kiwi
  pixelboy
  visrealm
  youki
